<?php


namespace app\common\model;


use app\common\service\redis\PoolRedis;
use app\model\AdminDormitory;
use app\model\AdminStaff;
use app\model\AdminStaffIcCard;
use app\model\AdminStudentDormitory;

class CacheRefreshHandler
{
    const STAFF_SIGN_KEY = 'staff:sign:';
    const DORMITORY_STU = AdminDormitory::DORMITORY_COUNT_CACHE_KEY."user_count_"; // 宿舍用户数量,{name/value}

    // 学生、职工操作刷新缓存 action,操作类型 add/edit/del
    // 宿舍用户、学校用户构成数量调整
    public static function hIncrBy($current, $origin = [])
    {
        $school_key = AdminStaff::SCHOOL_SEX_GROUP; // 学校用户构成数量

        // 宿舍、学校、性别调整
        if ($origin['school_id'] != $current['school_id']
            || $origin['sex'] != $current['sex'])
        {
            $redis = PoolRedis::instance();
            $redis->multi();
            if ($origin['sex'] != $current['sex']) {
                $redis->hIncrBy($school_key.$origin['school_id'],"{$origin['sex']}:{$origin['type']}", -1);
                $redis->hIncrBy($school_key.$current['school_id'],"{$current['sex']}:{$current['type']}", 1);
            }
            if ($current['type'] == AdminStaff::STUDENT && $origin['dormitory_id'] != $current['dormitory_id']) {
                // 宿舍用户数量减1
                $redis->hIncrBy(self::DORMITORY_STU.$origin['dormitory_id'], "value", -1);
                $redis->hIncrBy(self::DORMITORY_STU.$current['dormitory_id'], "value", 1);
            }
            $redis->exec();
        }
    }

    // 删除在线密码
    public static function onLinePwDel($uuid)
    {
        $redis = PoolRedis::instance();
        $keys = PoolRedis::scanAllForMatch('temp_pw:'.$uuid.":*");
        foreach ($keys as $key) {
            $redis->delete($key);
        }
    }

    // 单个宿舍编号调整
    public static function staffNumber($staff_id, $school_id, $student_dormitory_id, $action = 'add')
    {
        $redis = PoolRedis::instance();
        $distributionKey = AdminStudentDormitory::NO_KEY."{$school_id}:{$student_dormitory_id}";
        $noKey = $distributionKey.':no';
        $poolKey = $distributionKey.':pool';
        if ($action == 'add') {
            $no = $redis->rPop($poolKey);
            if ($no !== false) {
                $redis->hSet($noKey, $staff_id, $no);
            }
        } else {
            $redis->hDel($distributionKey.":score", $staff_id);
            $no = $redis->hGet($noKey, $staff_id);
            if ($no !== false) {
                // 保存到 del 列表
                $redis->hSet($distributionKey.':del', $no, $staff_id); // 编号+IC+SIM
                // 删除 no 列表
                $redis->hDel($noKey, $staff_id);
                // 保存到 pool 池
                $redis->lRem($poolKey, $no);
                $redis->lPush($poolKey, $no);
            }
        }
    }

    // 单个学校宿舍列表处理
    public static function storeHandler($action, $dormitory, $origin = [])
    {
        if (!in_array($action, ['add','edit','del'])) {
            return;
        }
        $redis = PoolRedis::instance();
        $school_key = AdminDormitory::DORMITORY_COUNT_CACHE_KEY."school_".$dormitory['school_id'];
        $redis->multi();
        switch ($action) {
            case 'add':
                $redis->sAdd($school_key, $dormitory['id']);
                $redis->hSet(self::DORMITORY_STU.$dormitory['id'],"name", $dormitory['name']);
                break;
            case 'edit':
                $redis->sMove($school_key, AdminDormitory::DORMITORY_COUNT_CACHE_KEY."school_".$origin['school_id'], $dormitory['id']);
                $redis->hIncrBy(self::DORMITORY_STU.$origin['id'],"value", -1);
                $redis->hIncrBy(self::DORMITORY_STU.$dormitory['id'],"value", 1);
                break;
            case 'del':
                // 删除宿舍用户数量
                $redis->del(self::DORMITORY_STU.$dormitory['id']);
                $redis->sRem($school_key, $dormitory['id']);
                break;
            default:
                $redis->discard(); // 退出事务处理模式
                return;
                break;
        }
        $redis->exec();
        return true;
    }

    // 用户活跃记录  key =》staff:sign:{Ymd}:{staffId} offset =》{h}
    public static function userActive($staff_id)
    {
        $redis = PoolRedis::instance();
        $key = self::STAFF_SIGN_KEY.date('Ymd').":".$staff_id;
        if (!$redis->exists($key)) {
            $offset = floor(date('G') / 2); // 24小时，下标最多到11
            $redis->setBit($key, $offset, 1);
            $redis->expire($key, 8*24*60*60); // 8天后过期
        }
    }

    // IC卡批量写入
    public static function IcCard()
    {
        $list = AdminStaffIcCard::where('is_delete', 0)
            ->where('ic_card', '<>', '')
            ->field('staff_id,ic_card')
            ->group('staff_id,ic_card')
            ->select()->toArray();
        if ($list) {
            $redis = PoolRedis::instance();
            $redis->multi();
            foreach ($list as $item) {
                $redis->hSetNx("smartCards", $item['ic_card'], $item['staff_id']);
            }
            $redis->exec();
        }
        return true;
    }
    // super sim卡批量写入
    public static function SimCard()
    {
        $list = AdminStaff::where('is_delete', 0)
            ->where('sim_card', '<>', '')
            ->field('id,sim_card')->select()->toArray();
        if ($list) {
            $redis = PoolRedis::instance();
            $redis->multi();
            foreach ($list as $item) {
                $redis->hSetNx("smartCards", $item['sim_card'], $item['id']);
            }
            $redis->exec();
        }
        return true;
    }
    // 学生宿舍编号批量写入
    public static function StudentDorNumber()
    {
        $redis = PoolRedis::instance();

        $distributionKey = AdminStudentDormitory::NO_KEY;
        $keys = PoolRedis::scanAllForMatch($distributionKey."*");
        foreach ($keys as $key) {
            $redis->del($key);
        }
        $dormitory = AdminStudentDormitory::where('is_delete', 0)
            ->field('school_id,id')->select()->toArray();
        $res = false;
        foreach ($dormitory as $item) {
            $res = AdminStudentDormitory::createNoList($item['school_id'], $item['id']);
        }
        if ($res) {
            $list = AdminStaffIcCard::hasWhere('staff', function($query) {
                    $query->where([
                        'is_delete' => 0,
                        'type' => AdminStaff::STUDENT
                    ])->field('id,school_id');
                })->alias('AdminStaffIcCard')
                ->where('AdminStaffIcCard.is_delete', 0)
                ->select()->toArray();
            foreach ($list as $item) {
                $stuKey = $distributionKey."{$item['school_id']}:{$item['student_dormitory_id']}";
                $no = $redis->rPop($stuKey.":pool");
                if ($no !== false) {
                    $redis->hSet($stuKey.":no", $item['staff_id'], $no);
                }
            }
        }
        return true;
    }

}